package com.pray.config;

import com.pray.security.filter.CorsFilter;
import com.pray.security.filter.JwtAuthenticationFilter;
import com.pray.security.filter.ValidateFilter;
import com.pray.security.handler.LogOutHandler;
import com.pray.security.handler.LoginFailureHandler;
import com.pray.security.handler.LoginSuccessHandler;
import com.pray.service.AccountService;
import com.pray.utils.JwtUtils;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer;
import org.springframework.security.config.annotation.web.configurers.SessionManagementConfigurer;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import org.springframework.security.web.util.matcher.RegexRequestMatcher;

/**
 * <p>
 * SecurityConfig
 * <p>
 *
 * @author 春江花朝秋月夜
 * @since 2023/9/3 0:43
 */
@Configuration
@EnableWebSecurity//开启之后会默认注册大量的过滤器链条
public class SecurityConfig {
    @Resource
    private AccountService accountService;
    @Resource
    private JwtAuthenticationFilter jwtAuthenticationFilter;
    @Resource
    private JwtUtils jwtUtils;//注入jwt的token生成工具
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private RedisTemplate redisTemplate;
    @Resource
    private ValidateFilter validateFilter;
    @Resource
    SessionRegistry sessionRegistry;
    @Resource
    CorsFilter corsFilter;
    @Bean
    //奇怪的问题
    //添加SpringSecurity的过滤器链
    //?
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        //重写认证失败的逻辑即可完成自定义权限认证失败的业务
        //访问被拒绝：抛出异常，注意不是登录的异常错误
        return http
                .headers(conf->conf.httpStrictTransportSecurity(hstsConfig -> {
                    hstsConfig.maxAgeInSeconds(0).includeSubDomains(true);
                }))
                .authorizeHttpRequests(conf->conf
                        .requestMatchers("/**").permitAll()
                )
                .formLogin(conf -> conf
                        .loginProcessingUrl("/auth/login")
                        .successHandler(new LoginSuccessHandler(accountService,jwtUtils,stringRedisTemplate))
                        .failureHandler(new LoginFailureHandler())
                        //匿名访问
                        .permitAll()
                )
                .httpBasic((basicConfigurer)->{
                    basicConfigurer.withObjectPostProcessor(new ObjectPostProcessor<BasicAuthenticationFilter>() {
                        @Override
                        public <O extends BasicAuthenticationFilter> O postProcess(O filter) {
                            filter.setSecurityContextRepository(new HttpSessionSecurityContextRepository());
                            return filter;
                        }
                    });
                })
                .csrf(AbstractHttpConfigurer::disable)//关闭跨域漏洞防御配置
//                .cors(AbstractHttpConfigurer::disable)
                .logout(conf->conf
                        .logoutUrl("/auth/logout")
                        .logoutSuccessHandler(new LogOutHandler(redisTemplate,jwtUtils)))
                .exceptionHandling(conf->conf.accessDeniedHandler((request, response, accessDeniedException) -> System.out.println("当前异常的登录信息："+accessDeniedException)))
//                .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
//                .addFilterBefore(corsFilter, UsernamePasswordAuthenticationFilter.class)
                .build();
    }

    @Bean
    public PasswordEncoder passwordEncoder(){
        return NoOpPasswordEncoder.getInstance();
    }
}
